#在Backtrader中实现布林带（Bollinger Bands）策略，主要是利用价格与上下布林带的关系来生成买卖信号。当价格触及或穿过上轨，可能视为超买信号，考虑卖出；当价格触及或穿过下轨，可能视为超卖信号，考虑买入。以下是一个简单的布林带策略示例
from datetime import datetime
import backtrader as bt
from strategies.utils.BaoStockPandasData import BaoStockPandasData
from utils.DataSource import get_stock_data2

class BollingerBandsStrategy(bt.Strategy):
    params = (
        ('period', 20),  # 移动平均线周期
        ('devfactor', 2),  # 标准差倍数
        ('order_percentage', 0.95),  # 交易资金占总资金的百分比
    )

    def __init__(self):
        self.data_close = self.datas[0].close
        self.order = None
        self.midband = bt.indicators.MovingAverageSimple(self.data_close, period=self.params.period)
        self.upperband = bt.indicators.BollingerBands(self.data_close, period=self.params.period, devfactor=self.params.devfactor).top
        self.lowerband = bt.indicators.BollingerBands(self.data_close, period=self.params.period, devfactor=self.params.devfactor).bot

    def next(self):
        if self.order:
            return  # 如果有订单在执行，则不执行新的买卖操作

        # 当价格触及或穿过下轨，视为买入信号
        if self.data_close[0] <= self.lowerband[0] and not self.position:
            amount_to_invest = (self.params.order_percentage * self.broker.cash) / self.data_close[0]
            self.buy(size=amount_to_invest)
            self.log(f"BUY EXECUTED --- Price: {self.data_close[0]}")

        # 当价格触及或穿过上轨，视为卖出信号
        elif self.data_close[0] >= self.upperband[0] and self.position:
            self.sell()
            self.log(f"SELL EXECUTED --- Price: {self.data_close[0]}")

    def log(self, txt, dt=None):
        ''' Logging function for this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            return  # 订单状态未最终确定，等待

        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(f"BUY EXECUTED --- Price: {order.executed.price}, Cost: {order.executed.value}, Commission: {order.executed.comm}")
            else:  # Sell
                self.log(f"SELL EXECUTED --- Price: {order.executed.price}, Size: {order.executed.size}, Commission: {order.executed.comm}")

        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')

        self.order = None

# 回测设置示例
if __name__ == '__main__':
    
    cerebro = bt.Cerebro()

    # 假设已经通过某种方式（如Yahoo Finance）获取了数据
    df = get_stock_data2("sh.600000", "2020-01-01", "2023-12-31")
    data = BaoStockPandasData(dataname=df)
    cerebro.adddata(data)

    cerebro.addstrategy(BollingerBandsStrategy, period=20, devfactor=2)

    cerebro.broker.setcash(100000.0)
    cerebro.broker.set_coc(True)  # 现金交易模式

    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
#这个策略中，我们定义了布林带的移动平均线周期（period）和标准差倍数（devfactor），利用bt.indicators.BollingerBands计算布林带的上下轨。当价格跌至下轨之下时，策略执行买入操作；当价格涨至上轨之上时，策略执行卖出操作。用户可以根据市场波动性调整标准差倍数，以适应不同的市场环境。